﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using Model;
using Core;
using System.Net;
using Newtonsoft.Json;

namespace DAL
{
    public class ReResource : BaseDAL
    {
        #region 资源记录入库
        /// <summary>
        /// 资源列表
        /// </summary>
        /// <param name="resources"></param>
        /// <returns></returns>
        public bool Save(List<Model.ReResource> resources)
        {
            if (resources == null || resources.Count <= 0)
                return false;
            Action<object> execBody = (state) =>
            {
                DownLoadResource((Model.ReResource)state);
            };
            Action<object> errHander = (state) =>
            {
                Log.errorlog(new Exception("资源编号为“" + state + "”的资源下载失败！"));
            };
            StringBuilder strSql = new StringBuilder();

            #region 查找需要同步的资源

            string _rsIds = string.Empty;
            resources.ForEach(rs =>
            {
                _rsIds += rs.ID + ",";
            });
            using (var conn = new SqlConnection(connection))
            {
                conn.Open();
                var rsSet = conn.Query(" select ID,IsCompleted,UploadTime from ReResource where ID  in( " + _rsIds.Trim(',') + ")").ToList();
                conn.Close();
                foreach (var rs in rsSet)
                {
                    resources.RemoveAll(item => item.ID == rs.ID && item.UploadTime.Value == rs.UploadTime && rs.IsCompleted);
                }
            }
            #endregion

            using (var conn = new SqlConnection(connection))
            {
                try
                {
                    resources.ForEach(resource =>
                    {
                        conn.Execute("if not exists ( select * from ReResource where ID=" + resource.ID + @")
                        begin
	                        insert into ReResource(ID,FatherID,ResourceName,ReOrginName,TechType,ReTypeCode,ApplyGrade,ApplySubject,Score,TimeLimit,UserID,ResourceSize,ResourceFormat,UploadTime,origin,EableShare,EableStart,IsCompleted) values (@ID,@FatherID,@ResourceName,@ReOrginName,@TechType,@ReTypeCode,@ApplyGrade,@ApplySubject,@Score,@TimeLimit,@UserID,@ResourceSize,@ResourceFormat,@UploadTime,@origin,@EableShare,@EableStart,@IsCompleted)
                        end
                        else
                        begin
	                        update ReResource set FatherID=@FatherID,ResourceName=@ResourceName,ReOrginName=@ReOrginName,TechType=@TechType,ReTypeCode=@ReTypeCode,ApplyGrade=@ApplyGrade,ApplySubject=@ApplySubject,Score=@Score,TimeLimit=@TimeLimit,UserID=@UserID,ResourceSize=@ResourceSize,ResourceFormat=@ResourceFormat,UploadTime=@UploadTime,origin=@origin,EableShare=@EableShare,EableStart=@EableStart where ID=@ID
                        end
                        if not exists (select * from TempResourceNeedDown where ResourceID=" + resource.ID + @")
                        begin
                            insert into TempResourceNeedDown (ResourceID) values(" + resource.ID + @") 
                        end", resource);
                        FunHelper.TryAsync(execBody, resource, null, null, errHander, resource.ID);
                    });
                }
                catch (Exception ex)
                {
                    Log.errorlog(ex);
                    return false;
                }
            }
            return true;
        }
        #endregion

        #region 资源分类下载
        /// <summary>
        /// 资源分类下载
        /// </summary>
        /// <param name="resource"></param>
        public void DownLoadResource(Model.ReResource resource)
        {
            switch (resource.ReTypeCode)
            {
                case "RE0001": DownResourceFile(resource); break; //课件
                case "RE0002": DownTestCombination(resource); break; //试卷
                case "RE0003": DownTask(resource); break; //自学任务单
                case "RE0004": ; break; //研讨任务单
                case "RE0005": ; break; //微课
                case "RE0006": ; Whiteboard(resource); break; //互动题板
                case "RE0007": DownResourceFile(resource); break; //教案
                case "RE0008": DownResourceFile(resource); break; //导学案
                case "RE0009": DownTestCombination(resource); break; //课堂测验
                case "RE0010": DownTestCombination(resource); break; //作业
                case "RE0011": DownTest(resource); break; //试题
                case "RE0012": ; break; //课前诊断单
                case "RE0013": DownResourceFile(resource); break; //素材
                case "RE0014": DownTestCombination(resource); break; //下载试题组合
                default: DownResourceFile(resource); break; //素材; break;
            }
        }
        #endregion

        #region 试题下载
        /// <summary>
        /// 试题下载
        /// </summary>
        /// <param name="resource"></param>
        public void DownTest(Model.ReResource resource)
        {
            WebClient wc = new WebClient();
            wc.Encoding = System.Text.Encoding.GetEncoding("utf-8");
            string strTest = wc.DownloadString(ConfigHelper.GetConfigString("RemoteUrl") + "/Ayyfford/GetTest/" + resource.ID);
            wc.Dispose();
            if (!string.IsNullOrWhiteSpace(strTest))
            {
                var dto = JsonConvert.DeserializeObject<TestDto>(strTest);

                using (var conn = new SqlConnection(connection))
                {
                    conn.Open();
                    IDbTransaction transaction = conn.BeginTransaction();
                    try
                    {
                        if (dto.tm != null)
                        {
                            conn.Execute("if not exists ( select * from ReTest where ID=" + dto.tm.ID + @")  
                                        begin 
                                            insert into ReTest(ID,BasicFather,QuestionTypeCode,QtypeName,SubjectCode,ApplicableSchool,ApplicableGrade,Points,QuestionRemark,QuestionDifficulty,UserID,ShareEable,CreatTime,QuestionAnalysis,TagTitle,Remark,ResourceID) values (@ID,@BasicFather,@QuestionTypeCode,@QtypeName,@SubjectCode,@ApplicableSchool,@ApplicableGrade,@Points,@QuestionRemark,@QuestionDifficulty,@UserID,@ShareEable,@CreatTime,@QuestionAnalysis,@TagTitle,@Remark,@ResourceID)
                                        end
                                            else
                                        begin
                                            update ReTest set BasicFather=@BasicFather,QuestionTypeCode=@QuestionTypeCode,QtypeName=@QtypeName,SubjectCode=@SubjectCode,ApplicableSchool=@ApplicableSchool,ApplicableGrade=@ApplicableGrade,Points=@Points,QuestionRemark=@QuestionRemark,QuestionDifficulty=@QuestionDifficulty,UserID=@UserID,ShareEable=@ShareEable,CreatTime=@CreatTime,QuestionAnalysis=@QuestionAnalysis,TagTitle=@TagTitle,Remark=@Remark,ResourceID=@ResourceID where ID=@ID                                    
                                        end", dto.tm, transaction);
                        }
                        if (dto.tg != null)
                        {
                            dto.tg.ForEach(tg =>
                            {
                                conn.Execute("if not exists ( select * from ReTestStem where ID=" + tg.ID + @")  
                                        begin 
                                            insert into ReTestStem(ID,TestID,StemContent,StemNumber,CorrectAnswer,QuestionTypeCode,QtypeName) values (@ID,@TestID,@StemContent,@StemNumber,@CorrectAnswer,@QuestionTypeCode,@QtypeName)
                                        end
                                            else
                                        begin
                                            update ReTestStem set TestID=@TestID,StemContent=@StemContent,StemNumber=@StemNumber,CorrectAnswer=@CorrectAnswer,QuestionTypeCode=@QuestionTypeCode,QtypeName=@QtypeName where ID=@ID
                                        end", tg, transaction);
                            });
                        }
                        if (dto.xx != null)
                        {
                            dto.xx.ForEach(xx =>
                            {
                                conn.Execute("if not exists ( select * from ReTestOption where ID=" + xx.ID + @")  
                                        begin 
                                            insert into ReTestOption(ID,StemID,OptionContent,OptionNumber,ConnectNumber) values (@ID,@StemID,@OptionContent,@OptionNumber,@ConnectNumber)
                                        end
                                            else
                                        begin
                                            update ReTestOption set StemID=@StemID,OptionContent=@OptionContent,OptionNumber=@OptionNumber,ConnectNumber=@ConnectNumber where ID=@ID
                                        end", xx, transaction);
                            });
                        }
                        transaction.Commit();
                        conn.Close();
                        SetResourceComplated(resource.ID);
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        Log.errorlog(ex);
                    }
                }

                FunHelper.TryAsync(() =>
                {
                    return DownTestLocalFile(resource.ID);
                });
            }
        }
        #endregion

        #region 作业及课堂测验及试卷下载
        /// <summary>
        /// 作业及课堂测验及试卷下载
        /// </summary>
        /// <param name="resource"></param>
        public void DownTestCombination(Model.ReResource resource)
        {
            WebClient wc = new WebClient();
            wc.Encoding = System.Text.Encoding.GetEncoding("utf-8");
            string strHomeWork = wc.DownloadString(ConfigHelper.GetConfigString("RemoteUrl") + "/Ayyfford/GetHomeWork/" + resource.ID);
            wc.Dispose();
            if (!string.IsNullOrWhiteSpace(strHomeWork))
            {
                var dto = JsonConvert.DeserializeObject<HomeWorkDto>(strHomeWork);
                string testIds = string.Empty;

                using (var conn = new SqlConnection(connection))
                {
                    conn.Open();
                    IDbTransaction transaction = conn.BeginTransaction();
                    try
                    {
                        #region 习题入库
                        if (dto.lrct != null)
                        {
                            dto.lrct.ForEach(rct =>
                            {
                                conn.Execute("if not exists ( select * from ReComTestType where ID=" + rct.Id + @")  
                                        begin 
                                            insert into ReComTestType(ID,ResourceID,QuestionTypeName,TypeScore,Number) values (@ID,@ResourceID,@QuestionTypeName,@TypeScore,@Number)
                                        end
                                            else
                                        begin
                                            update ReComTestType set ResourceID=@ResourceID,QuestionTypeName=@QuestionTypeName,TypeScore=@TypeScore,Number=@Number where Id=@Id
                                        end", rct, transaction);
                            });
                        }
                        if (dto.lrcd != null)
                        {
                            dto.lrcd.ForEach(rcd =>
                            {
                                conn.Execute("if not exists (select * from ReComDetail where Id=" + rcd.Id + @")  
                                        begin 
                                            insert into ReComDetail(Id,ComID,ResourceID,QuestionScore,Number) values (@Id,@ComID,@ResourceID,@QuestionScore,@Number)
                                        end
                                            else
                                        begin
                                            update ReComDetail set ComID=@ComID,ResourceID=@ResourceID,QuestionScore=@QuestionScore,Number=@Number where Id=@Id
                                        end", rcd, transaction);
                                testIds += rcd.ResourceID + ",";
                            });
                        }
                        #endregion

                        #region 下载试题资源
                        Func<bool> DownTest = () =>
                        {
                            if (!string.IsNullOrWhiteSpace(testIds))
                            {
                                WebClient _wc = new WebClient();
                                _wc.Encoding = System.Text.Encoding.GetEncoding("utf-8");
                                string strTestResource = _wc.DownloadString(ConfigHelper.GetConfigString("RemoteUrl") + "/Ayyfford/GetResourceSet/" + testIds);
                                _wc.Dispose();
                                if (!string.IsNullOrWhiteSpace(strTestResource))
                                {
                                    var ltr = JsonConvert.DeserializeObject<List<Model.ReResource>>(strTestResource);
                                    return Save(ltr);
                                }
                            }
                            return false;
                        };
                        Action ErrHander = () => { };
                        FunHelper.TryAsync(DownTest, null, ErrHander);
                        #endregion

                        transaction.Commit();
                        conn.Close();
                        SetResourceComplated(resource.ID);
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        Log.errorlog(ex);
                    }
                }
            }
        }
        #endregion

        #region 自学任务单下载
        /// <summary>
        /// 自学任务单下载
        /// </summary>
        /// <param name="resource"></param>
        public void DownTask(Model.ReResource resource)
        {
            WebClient wc = new WebClient();
            wc.Encoding = System.Text.Encoding.GetEncoding("utf-8");
            string strTask = wc.DownloadString(ConfigHelper.GetConfigString("RemoteUrl") + "/Ayyfford/GetTask/" + resource.ID);
            wc.Dispose();
            if (!string.IsNullOrWhiteSpace(strTask))
            {
                var dto = JsonConvert.DeserializeObject<TaskDto>(strTask);
                string rcdIds = string.Empty;

                using (var conn = new SqlConnection(connection))
                {
                    conn.Open();
                    IDbTransaction transaction = conn.BeginTransaction();
                    try
                    {
                        #region 表入库
                        if (dto.ltask != null)
                        {
                            dto.ltask.ForEach(task =>
                            {
                                conn.Execute("if not exists ( select * from ReTask where ID=" + task.ID + @")  
                                        begin 
                                            insert into ReTask(ID,ResourceId,TaskName,TaskType,TaskRequire,TaskGuide,FinishTime,TaskTeacher,CreateTime,ApplyGrade,ApplySubject) values (@ID,@ResourceId,@TaskName,@TaskType,@TaskRequire,@TaskGuide,@FinishTime,@TaskTeacher,@CreateTime,@ApplyGrade,@ApplySubject)
                                        end
                                            else
                                        begin
                                            update ReTask set ResourceId=@ResourceId,TaskName=@TaskName,TaskType=@TaskType,TaskRequire=@TaskRequire,TaskGuide=@TaskGuide,FinishTime=@FinishTime,TaskTeacher=@TaskTeacher,CreateTime=@CreateTime,ApplyGrade=@ApplyGrade,ApplySubject=@ApplySubject where ID=@ID
                                        end", task, transaction);
                            });
                        }
                        if (dto.lrcd != null)
                        {
                            dto.lrcd.ForEach(rcd =>
                            {
                                conn.Execute("if not exists (select * from ReResourceCombinationDetail where Id=" + rcd.Id + @")  
                                        begin 
                                            insert into ReResourceCombinationDetail(ID,TaskID,FResourceID,ResourceID,Number,CreatTime) values (@ID,@TaskID,@FResourceID,@ResourceID,@Number,@CreatTime)
                                        end
                                            else
                                        begin
                                            	update ReResourceCombinationDetail set TaskID=@TaskID,FResourceID=@FResourceID,ResourceID=@ResourceID,Number=@Number,CreatTime=@CreatTime where Id=@Id
                                        end", rcd, transaction);
                                rcdIds += rcd.ResourceID + ",";
                            });
                        }
                        #endregion

                        #region 下载资源集合
                        Func<bool> DownTaskResource = () =>
                        {
                            if (!string.IsNullOrWhiteSpace(rcdIds))
                            {
                                WebClient _wc = new WebClient();
                                _wc.Encoding = System.Text.Encoding.GetEncoding("utf-8");
                                string strTestResource = _wc.DownloadString(ConfigHelper.GetConfigString("RemoteUrl") + "/Ayyfford/GetResourceSet/" + rcdIds);
                                _wc.Dispose();
                                if (!string.IsNullOrWhiteSpace(strTestResource))
                                {
                                    var ltr = JsonConvert.DeserializeObject<List<Model.ReResource>>(strTestResource);
                                    return Save(ltr);
                                }
                            }
                            return false;
                        };
                        Action ErrHander = () => { };
                        FunHelper.TryAsync(DownTaskResource, null, ErrHander);
                        #endregion

                        transaction.Commit();
                        conn.Close();
                        SetResourceComplated(resource.ID);
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                        Log.errorlog(ex);
                    }
                }
            }
        }
        #endregion

        #region 互动白板下载
        /// <summary>
        /// 互动白板下载
        /// </summary>
        /// <param name="resource"></param>
        public void Whiteboard(Model.ReResource resource)
        {
            WebClient wc = new WebClient();
            wc.Encoding = System.Text.Encoding.GetEncoding("utf-8");
            string strWhiteboard = wc.DownloadString(ConfigHelper.GetConfigString("RemoteUrl") + "/Ayyfford/GetWhiteboard/" + resource.ID);
            wc.Dispose();

            if (!string.IsNullOrWhiteSpace(strWhiteboard))
            {
                var dto = JsonConvert.DeserializeObject<ResourceWhiteboard>(strWhiteboard);
                string testIds = string.Empty;

                using (var conn = new SqlConnection(connection))
                {
                    conn.Open();
                    try
                    {
                        #region 习题入库
                        if (dto != null)
                        {
                            conn.Execute("if not exists ( select * from ResourceWhiteboard where ID=" + dto.ID + @")  
                                        begin INSERT INTO [ResourceWhiteboard] ([ID],[ResourceID],[Content])values (@ID,@ResourceID,@Content)
                                        end
                                            else
                                        begin
                                            update ResourceWhiteboard set ResourceID=@ResourceID,Content=@Content where ID=@ID
                                        end", dto);
                        }
                        #endregion

                        SetResourceComplated(resource.ID);
                    }
                    catch (Exception ex)
                    {
                        Log.errorlog(ex);
                    }
                }
            }
        }
        #endregion

        #region 文件类型资源下载
        /// <summary>
        /// 文件类型资源下载
        /// </summary>
        /// <param name="resource"></param>
        public void DownResourceFile(Model.ReResource resource)
        {
            if (string.IsNullOrWhiteSpace(resource.ResourceName) || !resource.ResourceName.IsFilePath())
                return;
            FileDown<Model.ReResource> fd = new FileDown<Model.ReResource>(ConfigHelper.GetConfigString("RemoteSourceUrl") + resource.ResourceName, ConfigHelper.GetConfigString("SourceDir"), 10);
            fd.Data = resource;
            fd.CallBack = (Model.ReResource res) =>
            {
                SetResourceComplated(res.ID);
            };
            fd.Start();
        }
        #endregion

        #region 更新指定资源为完成状态
        /// <summary>
        /// 更新指定资源为完成状态
        /// </summary>
        /// <param name="rsid"></param>
        /// <returns></returns>
        bool SetResourceComplated(int rsid)
        {
            using (var conn = new SqlConnection(connection))
            {
                return conn.Execute("update ReResource set IsCompleted=1 where ID=@ID;delete TempResourceNeedDown where ResourceID=" + rsid, new { ID = rsid }) > 0;
            }
        }
        #endregion

        #region 重新下载未完成资源
        /// <summary>
        /// 重新下载未完成资源
        /// </summary>
        public void ReDownNotComplatedResource()
        {
            using (var conn = new SqlConnection(connection))
            {
                conn.Open();
                var ltrnd = conn.Query<TempResourceNeedDown>(" select * from TempResourceNeedDown where  DATEDIFF(mi, InsertedDate,GETDATE())>=5 and DATEDIFF(HOUR, InsertedDate,GETDATE())<=168 ").ToList();
                conn.Close();

                #region 下载资源集合
                if (ltrnd == null || ltrnd.Count <= 0)
                    return;

                string rcdIds = string.Empty;
                ltrnd.ForEach(rnd =>
                {
                    rcdIds += rnd.ResourceID + ",";
                });
                Func<bool> DownAsyncResource = () =>
                {
                    if (!string.IsNullOrWhiteSpace(rcdIds))
                    {
                        WebClient _wc = new WebClient();
                        _wc.Encoding = System.Text.Encoding.GetEncoding("utf-8");
                        string strResource = _wc.DownloadString(ConfigHelper.GetConfigString("RemoteUrl") + "/Ayyfford/GetResourceSet/" + rcdIds);
                        _wc.Dispose();
                        if (!string.IsNullOrWhiteSpace(strResource))
                        {
                            var ltr = JsonConvert.DeserializeObject<List<Model.ReResource>>(strResource);
                            return Save(ltr);
                        }
                    }
                    return false;
                };
                Action ErrHander = () => { };
                FunHelper.TryAsync(DownAsyncResource, null, ErrHander);
                #endregion
            }
        }
        #endregion

        #region 试题文件下载
        /// <summary>
        /// 试题文件下载
        /// </summary>
        /// <param name="resourceId"></param>
        /// <returns></returns>
        private bool DownTestLocalFile(int resourceId, bool redown = false)
        {
            WebClient wc = new WebClient();
            wc.Encoding = System.Text.Encoding.GetEncoding("utf-8");
            string strFileExt = wc.DownloadString(ConfigHelper.GetConfigString("RemoteUrl") + "/Ayyfford/GetFileExtByResourceId/" + resourceId);
            wc.Dispose();

            if (!string.IsNullOrWhiteSpace(strFileExt))
            {
                var lfe = JsonConvert.DeserializeObject<List<FileExt>>(strFileExt);
                try
                {
                    if (lfe != null && lfe.Count > 0)
                    {
                        lfe.ForEach(fe =>
                        {
                            fe.FilePath = "/" + fe.FilePath.Replace("\\", "/").Trim('/');
                            if (string.IsNullOrWhiteSpace(fe.FilePath) || !fe.FilePath.IsFilePath())
                                return;
                            FileDown<string> fd = new FileDown<string>(ConfigHelper.GetConfigString("RemoteUrl").TrimEnd('/') + "/" + fe.FilePath.TrimStart('/'), ConfigHelper.GetConfigString("SourceDir"), 10);
                            fd.Data = fe.FilePath;
                            if (redown)
                            {
                                fd.CallBack = (string _head) =>
                                {
                                    #region 移除下载的记录
                                    if (fd.IsSucess)
                                    {
                                        using (var conn = new SqlConnection(connection))
                                        {
                                            conn.Open();
                                            conn.Execute("delete FileExt where FilePath='" + _head + "' ResourceID=" + resourceId);
                                            conn.Close();
                                        }
                                    }
                                    #endregion
                                };
                            }
                            else
                            {
                                fd.CallBack = (string _head) =>
                                {
                                    #region 生成下载失败的记录
                                    if (!fd.IsSucess && !string.IsNullOrWhiteSpace(_head))
                                    {
                                        using (var conn = new SqlConnection(connection))
                                        {
                                            conn.Open();
                                            conn.Execute(@"insert into FileExt(
                                                        FilePath,ResourceID)
                                                         values (
                                                        @FilePath,@ResourceID)", new FileExt() { FilePath = _head, ResourceID = resourceId.ToString() });
                                            conn.Close();
                                        }
                                    }
                                    #endregion
                                };
                            }
                            fd.Start();
                        });
                    }
                }
                catch (Exception ex)
                {
                    #region 数据入库
                    using (var conn = new SqlConnection(connection))
                    {
                        conn.Open();
                        conn.Execute(@" if not exists (select * from TempResourceNeedDown where ResourceID=" + resourceId + @")
                        begin
                            insert into TempResourceNeedDown (ResourceID) values(" + resourceId + @") 
                        end");
                        conn.Close();
                    }
                    #endregion
                    Log.errorlog(ex);
                }
            }
            return false;
        }

        public void ReDownTestLocalFile()
        {
            List<FileExt> lfe = new List<FileExt>();
            using (var conn = new SqlConnection(connection))
            {
                conn.Open();
                lfe = conn.Query<FileExt>(" select * from FileExt ").ToList();
                conn.Close();
            }
            if (lfe != null && lfe.Count > 0)
            {
                lfe.ForEach(fe =>
                {
                    DownTestLocalFile(Convert.ToInt32(fe.ResourceID), true);
                });
            }
        }
        #endregion
    }
}
